package com.ermace.robo.jumper.game;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.gesture.GesturePoint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import com.ermace.robo.jumper.DifficultyActivity;
import com.ermace.robo.jumper.R;
import com.ermace.robo.jumper.game.GameObjects.Bitmaps;
import com.ermace.robo.jumper.game.GameObjects.GameObject;
import com.ermace.robo.jumper.game.GameObjects.Meteorite;
import com.ermace.robo.jumper.game.Player.Player;
import com.ermace.robo.jumper.game.Player.Position;
import com.ermace.robo.jumper.game.Player.Robot;
import com.ermace.robo.jumper.game.Player.RobotAI;
import com.ermace.robo.jumper.game.Player.RobotAI.AIStrength;
import com.ermace.robo.jumper.game.Player.RobotColour;
import com.ermace.robo.jumper.game.Player.AI.AIThread;
import com.ermace.robo.jumper.game.Player.AI.AI_Easy;
import com.ermace.robo.jumper.game.Player.AI.AI_Hard;
import com.ermace.robo.jumper.game.Player.AI.AI_Medium;


public class GameView extends SurfaceView implements SurfaceHolder.Callback {

	private int SWIPE_MIN_DISTANCE;
	private int SWIPE_MAX_OFF_PATH;
	private final int SWIPE_THRESHOLD_VELOCITY = 100;
	private static final int INVALID_POINTER_ID = -1;
	private static final long EVENT_TIME_INTERVAL = 10;
	private static float MAX_DOUBLETAP_SIZE;

	public static double SCREEN_WIDTH;
	public static double SCREEN_HEIGHT;
	public static double TOP_HEADER_HEIGHT;

	private boolean dialogIsDisplayed = false;
	private double fps;
	private double timer = 0;

	private GestureDetector gestureDetector; // listens for swipes

	// The active pointer is the one currently moving our robot.
	private int activePointerId = INVALID_POINTER_ID;
	private GesturePoint mLastPoint;

	private int pointerIdOne = INVALID_POINTER_ID; //pointer of first finger
	private GesturePoint mBeginPointOne;
	private GesturePoint mPointOne;
	private int pointerIdTwo = INVALID_POINTER_ID; //pointer of second finger
	private GesturePoint mBeginPointTwo;
	private GesturePoint mPointTwo;
	private int taps = 0;
	private long lastTap = 0;
	private /*volatile*/ boolean isMoving = false;

	private Activity activity;

	private Paint robotPaint; // Paint used to draw the robot
	private Paint backgroundPaint; // Paint used to clear the drawing area
	
	private Bitmap heart_icon;
	private Bitmap top_header;

	private Player player;
	private List<Robot> robots;
	private GameThread gameThread;
	//	private HandleEventThread handleEventThread;			// TODO remove

	private boolean gameOver;

	private Map currentMap;
	private AIThread aiThread;
	private Robot newRobot;
	private Intent intent;
	
	private SharedPreferences parameters;

	public static Resources resources;
	
	private List<GameObject> extraObjects;
	
	private Bitmap numbersheet;
	private int previousMultiplier = 1;
	private double numberScaling;
	
	private final Object gameThreadLock = new Object();
	private final Object aiThreadLock = new Object();
	
	private boolean isPaused = false;
	
	private String test = "no";
	
	// public constructor
	public GameView(Context context, AttributeSet attrs) {
		super(context, attrs); // call super's constructor
		//register SurfaceHolder.Callback listener
		getHolder().addCallback(this);
		activity = (Activity) context;
		//TODO
		resources = getResources();
		
		// intialize the GestureDetector
		gestureDetector = new GestureDetector(context, gestureListener);//new FlingGestureDetector());
		
		extraObjects = new ArrayList<GameObject>();
		robotPaint = new Paint();
		backgroundPaint = new Paint();
		heart_icon = BitmapFactory.decodeResource(resources, R.drawable.heart_icon);
		top_header = BitmapFactory.decodeResource(resources,R.drawable.top_header_game);
		numbersheet = BitmapFactory.decodeResource(resources, R.drawable.sprite_multiplier);
		aiThread = new AIThread(aiThreadLock);
		
	}

	public void initParameters(SharedPreferences parameters)
	{
		this.parameters = parameters;
	}

	public void initCurrentMap(Map map)
	{
		currentMap = map;
	}
	
	public void initIntent(Intent name)
	{
		this.intent = name;
	}
	
	public void addHighScore(int score)
	{
		
		SharedPreferences.Editor preferencesEditor = parameters.edit();
		preferencesEditor.putInt("lastScore", score); // store current search
		preferencesEditor.commit();

	}
	
	public void newGame()
	{
		stopThreads();
		aiThread = new AIThread(aiThreadLock);
		
		onSizeChanged((int)SCREEN_WIDTH, (int)SCREEN_HEIGHT, (int)SCREEN_WIDTH, (int)SCREEN_HEIGHT);
		timer = 0;
		isPaused = false;
		
	}

	public void stopGame()
	{
		stopThreads();	

	}
	
	public void pause() {
		if (gameThread != null)
			gameThread.pause(true);
		if (aiThread != null)
			aiThread.pause(true);
		
		isPaused = true;
	}
	
	public boolean isPaused()
	{
		return isPaused;
	}
	
	public void resume() {
		if (gameThread != null) {
			gameThread.previousFrameTime = System.currentTimeMillis();
			gameThread.pause(false);
		}
		if (aiThread != null) {
			aiThread.pause(false);
		}
		
		
		synchronized (gameThreadLock) {
			gameThreadLock.notify();
		}
		synchronized (aiThreadLock) {
			aiThreadLock.notify();
		}
		
		isPaused = false;
	}
	
	// called when the size of this View changes--including when this
	// view is first added to the view hierarchy
	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);

		MAX_DOUBLETAP_SIZE = h / 5;
		SWIPE_MIN_DISTANCE = h / 20;
		SWIPE_MAX_OFF_PATH = w / 10;
		SCREEN_WIDTH = w; // store the width
		SCREEN_HEIGHT = h; // store the height
		TOP_HEADER_HEIGHT = h / 20 + 5;
		
		double moveSpeed = w/4;
		double jumpSpeed = -h;
		double gravity = h/0.9;

		
		robots = new ArrayList<Robot>();
		player = new Player(gravity, moveSpeed, new Position(SCREEN_WIDTH / 2, Robot.MAX_Y), jumpSpeed, currentMap, robots, RobotColour.NONE, getContext());
		robots.add(player);
		
		if(currentMap.hasMeteorites())
		{
			extraObjects.add(new Meteorite(1, moveSpeed, R.drawable.heart_icon));
			extraObjects.add(new Meteorite(1, moveSpeed, R.drawable.heart_icon));
		}
		
		generateAI(moveSpeed, jumpSpeed, gravity);

		backgroundPaint.setColor(Color.WHITE);
		robotPaint.setColor(Color.GREEN);
		startThread(getHolder());
		test += "0";
	}

	/**
	 * 
	 */
	private void generateAI(double moveSpeed, double jumpSpeed, double gravity) {
		
		for (int i = 0; i < DifficultyActivity.getEasyAI(); i++) {
			newRobot = new RobotAI(AIStrength.EASY, gravity, moveSpeed, jumpSpeed, currentMap,
					robots, DifficultyActivity.getEasyColourList().get(i), getContext());
			robots.add(newRobot);
			aiThread.addAI(new AI_Easy(newRobot, robots));
		}
		
		for (int i = 0; i < DifficultyActivity.getMediumAI(); i++) {
			newRobot = new RobotAI(AIStrength.MEDIUM, gravity, moveSpeed, jumpSpeed, currentMap,
					robots, DifficultyActivity.getMediumColourList().get(i), getContext());
			robots.add(newRobot);
			aiThread.addAI(new AI_Medium(newRobot, robots));
		}
		
		for (int i = 0; i < DifficultyActivity.getHardAI(); i++) {
			newRobot = new RobotAI(AIStrength.HARD, gravity, moveSpeed, jumpSpeed, currentMap,
					robots, DifficultyActivity.getHardColourList().get(i), getContext());
			robots.add(newRobot);
			aiThread.addAI(new AI_Hard(newRobot, robots, currentMap));
		}
	}
	

	public boolean handleEvent(MotionEvent event) {
		
		if (! dialogIsDisplayed && player != null) {
			int action = event.getAction();
			long currentTime = System.currentTimeMillis();
			int pointerId;
			GesturePoint mBeginPoint;
	
			switch (action & MotionEvent.ACTION_MASK) {
				case MotionEvent.ACTION_DOWN:
					pointerId = event.getPointerId(0);
					mBeginPoint = new GesturePoint(event.getX(), event.getY(), currentTime);
					if (event.getDownTime() > EVENT_TIME_INTERVAL) {
						setActivePointer(pointerId, mBeginPoint);
						checkDoubleTap(mBeginPoint);
					}
					pointerIdOne = pointerId;
					mBeginPointOne= mBeginPoint;
					mPointOne = mBeginPoint;
					isMoving = true;
					break;
				case MotionEvent.ACTION_MOVE:
					if (activePointerId != pointerIdOne && currentTime - mBeginPointOne.timestamp > EVENT_TIME_INTERVAL && 
					(mBeginPointTwo == null || mBeginPointOne.timestamp > mBeginPointTwo.timestamp)) {
						setActivePointer(pointerIdOne, mPointOne);	// pointerIdOne becomes the active pointer
					} else if (activePointerId != pointerIdTwo && pointerIdTwo != INVALID_POINTER_ID && 
							currentTime - mBeginPointTwo.timestamp > EVENT_TIME_INTERVAL &&
							mBeginPointTwo.timestamp > mPointOne.timestamp) {
						setActivePointer(pointerIdTwo, mBeginPointTwo);	// pointerIdTwo becomes the active pointer
					} if (activePointerId != INVALID_POINTER_ID /*&& 
							currentTime - mLastPoint.timestamp > EVENT_TIME_INTERVAL*/) {
						int pointerIndex = event.findPointerIndex(activePointerId);
						if (pointerIndex != -1) {
							float x = event.getX(pointerIndex);	// update move position of the player to current pos
							float y = event.getY(pointerIndex);
							player.move(new Position(x, y));
							mLastPoint = new GesturePoint(x, y, currentTime);
						}
					} if (activePointerId == pointerIdOne) {
						mPointOne = mLastPoint;
						int index = event.findPointerIndex(pointerIdTwo);
						if (index != -1) {
							GesturePoint mPoint = new GesturePoint(event.getX(index), event.getY(index),currentTime);
							if (mPoint != null)
								mPointTwo = mPoint;
						}
					} else {
						int index = event.findPointerIndex(pointerIdOne);
						if (index != -1) {
							GesturePoint mPoint = new GesturePoint(event.getX(index), event.getY(index),currentTime);
							if (mPoint != null)
								mPointOne = mPoint;
						}
						mPointTwo = mLastPoint;
					}
					break;
				case MotionEvent.ACTION_POINTER_DOWN: // an extra finger appears on the screen :o
					pointerIdTwo = event.getPointerId(event.getActionIndex());
					mBeginPoint = new GesturePoint(event.getX(pointerIdTwo), event.getY(pointerIdTwo),currentTime);
					if (mBeginPoint != null)
						checkDoubleTap(mBeginPoint);
					mBeginPointTwo = mBeginPoint;
					break;
				case MotionEvent.ACTION_POINTER_UP: // one finger leaves the screen :(
					int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) 
											>> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
					pointerId = event.getPointerId(pointerIndex);
		
					if (pointerId == pointerIdOne) { //First was lifted but there is a second on the screen
						pointerIdOne = pointerIdTwo;
						mBeginPointOne = mBeginPointTwo;
						mPointOne = mPointTwo;
						pointerIdTwo = INVALID_POINTER_ID;
					} else if (pointerId == pointerIdTwo) {
						pointerIdTwo = INVALID_POINTER_ID;
					}
		
					if (pointerId == activePointerId) // this was our active pointer
						setActivePointer(pointerIdOne, mPointOne);
					break;
				case MotionEvent.ACTION_UP:	// No more fingers on the screen
					synchronized (this) {
						isMoving = false;
					}
					pointerIdOne = INVALID_POINTER_ID;
					activePointerId = INVALID_POINTER_ID;
					player.stop();
					break;
			}
	
			//		if (action == MotionEvent.ACTION_UP) {
			//			player.stop();
			//		} else if (action == MotionEvent.ACTION_DOWN) {
			//			player.move(event);
			//		} else if (action == MotionEvent.ACTION_MOVE) {
			//			player.move(event);
			//		}
	
			return gestureDetector.onTouchEvent(event);
		}
		
		return true;
	}

	private void checkDoubleTap(GesturePoint touchPoint) {
		GesturePoint[] points = {mPointOne, mPointTwo};
		boolean correct = false;

		for (GesturePoint point: points) {
			if (point != null) {
				Position beginPos = new Position(point.x, point.y);
				Position touchPos = new Position(touchPoint.x, touchPoint.y);
				if (beginPos.getDistanceTo(touchPos) < MAX_DOUBLETAP_SIZE &&
						touchPoint.timestamp - point.timestamp < 25 * EVENT_TIME_INTERVAL) {
					if (System.currentTimeMillis() - lastTap > 25 * EVENT_TIME_INTERVAL) // too long from previous tap
						taps = 1;														// but it is a valid one
					else 
						taps++;
					lastTap = System.currentTimeMillis();
					correct = true;
					break;
				}
			}
		}

		if (correct) {
			if (taps == 1) { //TODO moet eig 2 zijn ma snap nie wrm nie
				player.jump();
				taps = 0;
			}
		} else
			taps = 0;
	}
	
	public boolean gameOver()
	{
		return gameOver;
	}

	private void setActivePointer(int pointerId, GesturePoint beginPoint) {
		if (beginPoint != null) {
			activePointerId = pointerId;
			mLastPoint = beginPoint;
			player.move(new Position(mLastPoint.x, mLastPoint.y));
		}
	}

	private void drawGameElements(Canvas canvas, double elapsedTimeMS) {
		// clear the background
		if (canvas != null) {
			
			
			currentMap.draw(canvas);
			for(GameObject obj: extraObjects)
				canvas.drawBitmap(heart_icon, null, obj.getRect(), null);
			
			drawMultiplier(canvas, elapsedTimeMS);	
			
			for (Robot robot: robots)
				if (robot.isAlive() && robot != player || robot.isExploding())
					robot.draw(canvas);

			if (player.isAlive() || player.isExploding())
				player.draw(canvas);
			else {
				drawRespawnOverlay(canvas);
			}

			if(player.getLives() == 0)
			{				
				player.incScore();
				gameOver = true;
				isPaused = true;
				pause();
				addHighScore(player.getScore());
				activity.startActivity(intent);
				activity.finish();
			}
			
			// Draw the top header
			drawTopHeader(canvas);
			
		}
	}
	
	/**
	 * @param canvas
	 */
	private void drawRespawnOverlay(Canvas canvas) {
		
		Paint fadePaint = new Paint();
		Paint timePaint = new Paint();
		
		timePaint.setColor(Color.GREEN);
		fadePaint.setColor(Color.BLACK);
		fadePaint.setAlpha(100);
		
		int width = numbersheet.getWidth() / 11;
		int height = numbersheet.getHeight() / 2;
		
		canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), fadePaint);
		canvas.drawBitmap(numbersheet, new Rect( (int)   (player.getRespawnTime() + 1) * width, 0,  (int) (player.getRespawnTime() + 2) * width, height), new Rect((int)(SCREEN_WIDTH/2 - SCREEN_WIDTH/20),(int) (SCREEN_HEIGHT / 2 - SCREEN_WIDTH / 20),(int) (SCREEN_WIDTH/2 + SCREEN_WIDTH / 20), (int) (SCREEN_HEIGHT / 2 + SCREEN_WIDTH / 20)), null);
		//canvas.drawText("" + (int) player.getRespawnTime(),(float)(5 * SCREEN_WIDTH / 10) ,(float)(5 * SCREEN_HEIGHT / 10) , timePaint);
	
	}

	/**
	 * @param canvas
	 */
	private void drawTopHeader(Canvas canvas) {
		Paint topHeaderPaint = new Paint();
		topHeaderPaint.setARGB(200, 220, 220, 240);
		
		//canvas.drawRect(0, 0, canvas.getWidth(), (float) TOP_HEADER_HEIGHT, topHeaderPaint);
		canvas.drawBitmap(top_header, null, new Rect(0, 0, canvas.getWidth(),(int) TOP_HEADER_HEIGHT) , null);
		
		int size = (int)SCREEN_HEIGHT / 25;
		for (int i = 0; i < player.getLives(); i++) {
			int offset = (int)(9.8 * SCREEN_WIDTH / 10) - size * i - (size / 5) * i;
			Rect rect = new Rect(offset - size, 5, offset, 5 + size);
			canvas.drawBitmap(heart_icon, null, rect, null);
		}
		String time;
		if((int)timer/1000 %60 < 10)
			time = "0" + ((int) timer/60000) + " : 0" + (int)timer/1000 %60;
		else
			time = "0" + ((int) timer/60000) + " : " + (int)timer/1000 %60;
		
		robotPaint.setTextSize( (int) TOP_HEADER_HEIGHT / 2);
		canvas.drawText("" + player.getScore(),(float)(4.9 * SCREEN_WIDTH / 10) , (float) (0.5 * SCREEN_HEIGHT /10) , robotPaint);
		canvas.drawText( time ,(float)(0.3 * SCREEN_WIDTH / 10) , (float) (0.5 * SCREEN_HEIGHT /10) , robotPaint);

}



	//class FlingGestureDetector extends SimpleOnGestureListener {
	SimpleOnGestureListener gestureListener = new SimpleOnGestureListener() {
		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
			try {
				if (Math.abs(e1.getX() - e2.getX()) > SWIPE_MAX_OFF_PATH)
					return false;
				// up swipe
				if(e1.getY() - e2.getY() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
					player.jump();
					return true;
				}
			} catch (Exception e) {
				// nothing
			}
			return false;
		}

		@Override
		public boolean onDoubleTap(MotionEvent e) {
			player.jump();
			return true;
		}
	};

	@Override
	public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2,
			int arg3) {
		// TODO Auto-generated method stub

	}

	@Override
	public void surfaceCreated(SurfaceHolder arg0) {
		// TODO Auto-generated method stub

	}
	


	@Override
	public void surfaceDestroyed(SurfaceHolder arg0) {
		// TODO Auto-generated method stub

	}
	
	public void startThread(SurfaceHolder arg0)
	{
		gameThread = new GameThread(arg0);
		gameThread.start();
	}
	
	public void stopThreads()
	{
		boolean retry = true;
		gameThread.stopThread();
		aiThread.stopThread();
		while (retry)
		{
			try
			{
				gameThread.join();
				aiThread.join();
				retry = false;
			}
			catch (InterruptedException e)
			{

			}
		}
	}
	
	private void drawMultiplier(Canvas canvas, double elapsedTimeMS)
	{
		
		elapsedTimeMS = elapsedTimeMS / 1000;
		
		int width = numbersheet.getWidth() / 11;
		int height = numbersheet.getHeight() / 2;
		
		int multi = player.getComboMultiplicator() - 1;
				
		if(numberScaling < 1 && numberScaling + elapsedTimeMS < 1)
			numberScaling += elapsedTimeMS;
		else
			numberScaling = 1;
		
		// canvas.drawText("" + multi, 100, 100, robotPaint); remove at END
		
		double startX =  4 * SCREEN_WIDTH / 10;
		double startY = SCREEN_HEIGHT / 10;
		
		int toDraw = 0;
		
		if(player.getPosition().getDistanceTo(new Position(startX + SCREEN_WIDTH /20 , startY + SCREEN_WIDTH /20 )) < SCREEN_WIDTH / 5)
				toDraw = 1;
		
				
		if(multi > 1 && previousMultiplier == multi)
		{
			if(multi > 9)
			{
				if(numberScaling < 0.5)
				{
					canvas.drawBitmap(numbersheet, new Rect( 0, toDraw * height,  width,  height * ( 1 + toDraw )) , new Rect( (int) (startX - SCREEN_WIDTH / 10 * (numberScaling) / 2) , (int) (startY - SCREEN_WIDTH / 10 * (numberScaling / 2)), (int) (startX + SCREEN_WIDTH / 10 * (1 + numberScaling / 2)), (int) (startY + SCREEN_WIDTH / 10 * (1 + numberScaling /2))), null);
					canvas.drawBitmap(numbersheet, new Rect( width * (int) (multi / 10 + 2), toDraw * height,  width * ((int) (multi / 10) + 3) ,  height * ( 1 + toDraw )), new Rect( (int) (startX + SCREEN_WIDTH / 10 * (1 + numberScaling / 2)), (int) (startY - SCREEN_WIDTH / 10 * (numberScaling) / 2), (int) (startX + 2 * SCREEN_WIDTH / 10 * (1 + 3 * numberScaling / 4)), (int) (startY + SCREEN_WIDTH / 10 * ( 1 + numberScaling /2))), null);
					canvas.drawBitmap(numbersheet, new Rect( width * (multi %10), toDraw * height,  width * (multi %10 + 1) ,  height * ( 1 + toDraw )) , new Rect( (int) (startX + 2 * SCREEN_WIDTH / 10 * (1 + numberScaling / 2)), (int) (startY - SCREEN_WIDTH / 10 * (numberScaling) / 2), (int) (startX + 3 * SCREEN_WIDTH / 10 * (1 + 3 * numberScaling / 4)), (int) (startY + SCREEN_WIDTH / 10 * ( 1 + numberScaling /2))), null);
				}
				else
				{
					canvas.drawBitmap(numbersheet, 	new Rect( 0, toDraw * height,  width,  height * ( 1 + toDraw )) , new Rect( (int) (startX - SCREEN_WIDTH / 10 * (1 - numberScaling) / 2), (int) ( startY - SCREEN_WIDTH / 10 * (1 - numberScaling) / 2), (int) (startX + SCREEN_WIDTH / 10 * (1.5 - numberScaling /2)), (int) (startY + SCREEN_WIDTH / 10 * (1.5 - numberScaling / 2))), null);
					canvas.drawBitmap(numbersheet,  new Rect( width * (int) (multi / 10 + 2), toDraw * height ,  width * ((int) (multi / 10) + 3),  height * ( 1 + toDraw )), new Rect( (int) (startX + SCREEN_WIDTH / 10 * (1.5 - numberScaling / 2) ), (int) (startY - SCREEN_WIDTH / 10 * (1 - numberScaling) / 2), (int) (startX + 2.75 * SCREEN_WIDTH / 10 - (numberScaling - 0.5) * 1.5 *  SCREEN_WIDTH / 10 ), (int) (startY + SCREEN_WIDTH / 10 * (1.5 - numberScaling / 2))), null);
					canvas.drawBitmap(numbersheet,  new Rect( width * (multi %10), toDraw * height,  width * (multi %10 + 1),  height * ( 1 + toDraw )), new Rect( (int) (startX + 2 * SCREEN_WIDTH / 10 * (1.5 - numberScaling / 2) ), (int) (startY - SCREEN_WIDTH / 10 * (1 - numberScaling) / 2), (int) (startX + 4.25 * SCREEN_WIDTH / 10 - (numberScaling - 0.5) * 2.5 *  SCREEN_WIDTH / 10 ), (int) (startY + SCREEN_WIDTH / 10 * (1.5 - numberScaling / 2))), null);
				}
			}
			else
			{
				if(numberScaling < 0.5)
				{
					canvas.drawBitmap(numbersheet, new Rect( 0, toDraw * height,  width,  height * ( 1 + toDraw )) , new Rect( (int) (startX - SCREEN_WIDTH / 10 * (numberScaling) / 2) , (int) (startY - SCREEN_WIDTH / 10 * (numberScaling / 2)), (int) (startX + SCREEN_WIDTH / 10 * (1 + numberScaling / 2)), (int) (startY + SCREEN_WIDTH / 10 * (1 + numberScaling /2))), null);
					canvas.drawBitmap(numbersheet, new Rect( width * (multi + 1), toDraw * height,  width * (multi + 2) ,  height * ( 1 + toDraw )), new Rect( (int) (startX + SCREEN_WIDTH / 10 * (1 + numberScaling / 2)), (int) (startY - SCREEN_WIDTH / 10 * (numberScaling) / 2), (int) (startX + 2 * SCREEN_WIDTH / 10 * (1 + 3 * numberScaling / 4)), (int) (startY + SCREEN_WIDTH / 10 * ( 1 + numberScaling /2))), null);
				}
				else
				{
					canvas.drawBitmap(numbersheet, 	new Rect( 0, toDraw * height,  width,  height * ( 1 + toDraw )) , new Rect( (int) (startX - SCREEN_WIDTH / 10 * (1 - numberScaling) / 2), (int) ( startY - SCREEN_WIDTH / 10 * (1 - numberScaling) / 2), (int) (startX + SCREEN_WIDTH / 10 * (1.5 - numberScaling /2)), (int) (startY + SCREEN_WIDTH / 10 * (1.5 - numberScaling / 2))), null);
					canvas.drawBitmap(numbersheet,  new Rect( width * (multi + 1), toDraw * height,  width * (multi + 2),  height * ( 1 + toDraw )), new Rect( (int) (startX + SCREEN_WIDTH / 10 * (1.5 - numberScaling / 2) ), (int) (startY - SCREEN_WIDTH / 10 * (1 - numberScaling) / 2), (int) (startX + 2.75 * SCREEN_WIDTH / 10 - (numberScaling - 0.5) * 1.5 *  SCREEN_WIDTH / 10 ), (int) (startY + SCREEN_WIDTH / 10 * (1.5 - numberScaling / 2))), null);
				}
			}
		}
		else
		{
			numberScaling = 0;			
		}
		
		previousMultiplier = multi;
	}
	
	private void showGameOverDialog(String message, int score) // TODO nog nodig?
	{
		
		gameThread.stopThread();
		aiThread.stopThread();

		final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(getContext());
		dialogBuilder.setTitle("Game Over");
		dialogBuilder.setCancelable(false);
		
		dialogBuilder.setMessage(message);


		dialogBuilder.setPositiveButton("do you want to start again?",
				new DialogInterface.OnClickListener(){
			@Override
			public void onClick(DialogInterface dialog, int which)
			{
				dialogIsDisplayed = false;
			
				activity.finish();
			}
		}
				);
		activity.runOnUiThread(
				new Runnable() {
					@Override
					public void run()
					{
						dialogIsDisplayed = true;
						dialogBuilder.show();
					}
				}
				);
	}
	
	//Thread subclass to control the game loop
	private class GameThread extends Thread {
		private SurfaceHolder surfaceHolder; // for manipulating canvas
		private volatile boolean threadIsRunning = true; // running by default
		private volatile boolean threadIsPaused = false; // not paused by default
		private long previousFrameTime;

		// initializes the surface holder
		public GameThread(SurfaceHolder holder) {
			surfaceHolder = holder;
			setName("GameThread");
		}

		// stops the thread
		public void stopThread() {
			threadIsRunning = false;
			threadIsPaused = true;
			
			synchronized (gameThreadLock) {
				gameThreadLock.notify();
			}
		}
		
		public void pause(boolean pause) {
			threadIsPaused = pause;
			
//			synchronized (lock) {
//				lock.notifyAll();
//			}
		}

		//controls the game loop
		@Override
		public void run() {
			Canvas canvas = null; // used for drawing
			previousFrameTime = System.currentTimeMillis();
			
			try {
				if (! aiThread.isAlive())
					aiThread.start();
			} catch (IllegalThreadStateException e) {
				
			}
			
			while (threadIsRunning) {
				if (! threadIsPaused) {
					try {
						canvas = surfaceHolder.lockCanvas(null);
	
						// lock the surfaceHolder for drawing
						synchronized(surfaceHolder) {
							long currentTime = System.currentTimeMillis();
							double elapsedTimeMS = currentTime - previousFrameTime;
							fps = 1000 / elapsedTimeMS;
							timer += elapsedTimeMS;
							//							totalElapsedTime += elapsedTimeMS / 1000.00;
							if (isMoving && player.isAlive() && mLastPoint != null && !dialogIsDisplayed)
								player.move(new Position(mLastPoint.x, mLastPoint.y));
							for(GameObject obj: extraObjects)
								{
									obj.update(elapsedTimeMS);
									for(Robot robot: robots)
										obj.interact(robot);
								}
							for(Robot robot: robots)
								robot.updatePosition(elapsedTimeMS);
							
							for (Robot robot: robots)
								if (robot.isAlive())
									robot.checkCollision(currentMap.getObjects());
							drawGameElements(canvas, elapsedTimeMS);
							
							previousFrameTime = currentTime;
						}
					} finally {
						if (canvas != null)
							surfaceHolder.unlockCanvasAndPost(canvas);
					}
				}
				
//				if (threadIsRunning) {
//					synchronized (gameThreadLock) {
//						try {
//							gameThreadLock.wait();
//						} catch (InterruptedException e) {
//							// interrupted
//							return;
//						} 
//					}
//				}
			}
		}
	}
	
}
